/*
 *  Copyright 2019-2020 Zheng Jie
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package me.zhengjie.modules.system.service.impl;

import cn.hutool.core.util.ObjectUtil;
import me.zhengjie.modules.system.domain.ExamInfo;
import me.zhengjie.modules.system.service.AtmrExamTypeService;
import me.zhengjie.modules.system.service.AtmrService;
import me.zhengjie.modules.system.service.ExamDatabaseService;
import me.zhengjie.modules.system.service.dto.*;
import me.zhengjie.utils.*;
import lombok.RequiredArgsConstructor;
import me.zhengjie.modules.system.repository.ExamInfoRepository;
import me.zhengjie.modules.system.service.ExamInfoService;
import me.zhengjie.modules.system.service.mapstruct.ExamInfoMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;

/**
 * @website https://el-admin.vip
 * @description 服务实现
 * @author zhaoxiancheng
 * @date 2021-11-18
 **/
@Service
@RequiredArgsConstructor
@CacheConfig(cacheNames="examInfo")
public class ExamInfoServiceImpl implements ExamInfoService {

    private final ExamInfoRepository examInfoRepository;
    private final ExamInfoMapper examInfoMapper;

    @Autowired
    AtmrExamTypeService atmrExamTypeService;

    @Autowired
    AtmrService atmrService;

    @Autowired
    ExamDatabaseService examDatabaseService;

    @Override
    public Map<String,Object> queryAll(ExamInfoQueryCriteria criteria, Pageable pageable){
        Page<ExamInfo> page = examInfoRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
        return PageUtil.toPage(page.map(examInfoMapper::toDto));
    }

    @Override
    public List<ExamInfoDto> queryAll(ExamInfoQueryCriteria criteria){
        return examInfoMapper.toDto(examInfoRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)));
    }

    @Override
    @Transactional
    @Cacheable(value="id",key="#id")
    public ExamInfoDto findById(Integer id) {
        ExamInfo examInfo = examInfoRepository.findById(id).orElseGet(ExamInfo::new);
        ValidationUtil.isNull(examInfo.getId(),"ExamInfo","id",id);
        return examInfoMapper.toDto(examInfo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ExamInfoDto create(ExamInfo resources) {
        return examInfoMapper.toDto(examInfoRepository.save(resources));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CachePut(value="id",key="#resources.getId()")
    public void update(ExamInfo resources) {
        ExamInfo examInfo = examInfoRepository.findById(resources.getId()).orElseGet(ExamInfo::new);
        ValidationUtil.isNull( examInfo.getId(),"ExamInfo","id",resources.getId());
        examInfo.copy(resources);
        examInfoRepository.save(examInfo);
    }

    @Override
    @CacheEvict(value="id",allEntries=true)
    public void deleteAll(Integer[] ids) {
        for (Integer id : ids) {
            examInfoRepository.deleteById(id);
        }
    }

    @Transactional
    @Override
    public void stopUseOldExamInfoByDatabaseId(Long databaseId) {
        if(ObjectUtil.isEmpty(databaseId)){
            return;
        }
        examInfoRepository.updateExamInfoByExamDatabaseId(databaseId);
    }

    @Override
    public void download(List<ExamInfoDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (ExamInfoDto examInfo : all) {
            Map<String,Object> map = new LinkedHashMap<>();
            map.put("题目", examInfo.getExam());
            map.put("答案", examInfo.getAnswer());
            map.put("测试题库Id", examInfo.getExamDatabaseId());
            map.put("分值", examInfo.getScore());
            map.put("选项", examInfo.getChose());
            map.put("是否可用：0-可用；1-停用", examInfo.getStatus());
            map.put("题型编号", examInfo.getExamTypeId());
            map.put("答案是否唯一：0-是；1-否", examInfo.getIsOnly());
            map.put("得分说明", examInfo.getDescription());
            map.put("试题title", examInfo.getTitle());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    /**
     * 创建试题
     *
     * @param
     * @return
     */
    @Override
    public List<ExamInfoDto> createExamInfo(Integer atmrExamTypeId,Long examDatabaseId){
        List<ExamInfoDto> resultExam = new ArrayList<>();
        try {
            AtmrExamTypeQueryCriteria criteria = new AtmrExamTypeQueryCriteria();
            criteria.setAtmrId(String.valueOf(atmrExamTypeId));
            List<AtmrExamTypeDto> aetList = atmrExamTypeService.queryAll(criteria);
            if(aetList != null && aetList.size() > 0)
            {
                for(AtmrExamTypeDto aet : aetList)
                {
                    String examTypeId = aet.getExamTypeId();
                    String examNum = aet.getExamNum();
                    ExamInfoQueryCriteria examData = new ExamInfoQueryCriteria();
                    examData.setExamTypeId(examTypeId);
                    examData.setAtmrId(aet.getAtmrId());
                    examData.setStatus("0");
                    examData.setExamDatabaseId(examDatabaseId);
                    List<ExamInfoDto> examInfoList = queryAll(examData);
                    if(examInfoList != null && examInfoList.size() > 0)
                    {
                        Set<Integer> indexSet = random(examInfoList.size(), Integer.parseInt(examNum));
                        for(Integer index : indexSet)
                        {
                            resultExam.add(examInfoList.get(index));
                        }
                    }
                }
                for(ExamInfoDto examPd : resultExam)
                {
                    if(StringUtils.isNotBlank(examPd.getChose())){
                        String[] options = examPd.getChose().split(";");
                        examPd.setOptions(options);
                    }
                    if(StringUtils.isNotBlank(examPd.getScore())){
                        String[] scores = examPd.getScore().split(";");
                        examPd.setScores(scores);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return resultExam;
    }

    /**
     *
     * @param atmrId
     * @return
     */
    @Override
    public List<ExamInfoDto> createExamInfoNew(Long atmrId){
        List<ExamInfoDto> resultExam = new ArrayList<>();
        try {
            AtmrDto atmrDto = atmrService.findById(atmrId.intValue());
            Long examDatabaseId = atmrDto.getExamDatabaseId();
            if(ObjectUtil.isEmpty(examDatabaseId) || examDatabaseId <= 0){
                ExamDatabaseQueryCriteria databaseQueryCriteria = new ExamDatabaseQueryCriteria();
                databaseQueryCriteria.setAtmrExamTypeId(atmrId);
                List<ExamDatabaseDto> examDatabaseDtoList =  examDatabaseService.queryAll(databaseQueryCriteria);
                if(CollectionUtils.isEmpty(examDatabaseDtoList)){
                    return null;
                } else if(examDatabaseDtoList.size() == 1){
                    examDatabaseId = examDatabaseDtoList.get(0).getDatabaseId();
                } else {
                    Random r = new Random();
                    int index = r.nextInt()%examDatabaseDtoList.size();
                    examDatabaseId = examDatabaseDtoList.get(index).getDatabaseId();
                }

            }

            ExamInfoQueryCriteria examData = new ExamInfoQueryCriteria();
            examData.setStatus("0");
            examData.setExamDatabaseId(examDatabaseId);
            resultExam = queryAll(examData);
            for(ExamInfoDto examPd : resultExam) {
                if(StringUtils.isNotBlank(examPd.getChose())){
                    String[] options = examPd.getChose().split(";");
                    examPd.setOptions(options);
                }
                if(StringUtils.isNotBlank(examPd.getScore())){
                    String[] scores = examPd.getScore().split(";");
                    examPd.setScores(scores);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return resultExam;
    }

    /**
     *
     * @param total
     * @param examCount
     * @return
     */
    private Set<Integer>  random(int total,int examCount) {
        Set<Integer> set = new HashSet<>();
        Random r = new Random();
        int num = 0;
        while (num < examCount){
            int number = r.nextInt(total) ;
            //编写条件 当set中没有这个数 且 这个数大于等于20
            if(!set.contains(number)){
                set.add(number);
                num++;
            }
        }
        Set<Integer> sortSet = new TreeSet<Integer>(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1.compareTo(o2);//降序排列
            }
        });
        sortSet.addAll(set);
        return sortSet;
    }
}